package com.easymall.web;

import com.easymall.domain.Category;
import com.easymall.domain.Prod;
import com.easymall.service.CategoryService;
import com.easymall.service.ProdService;
import com.easymall.util.BaseFactory;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@WebServlet(name = "ProdAddServlet")
public class ProdAddServlet extends HttpServlet {

    private ProdService prodService;
    private CategoryService categoryService;

    private String uploadPath = "WEB-INF/upload";

    @Override
    public void init() throws ServletException {
        try {
            prodService = BaseFactory.getFactory().getInstance(ProdService.class);
            categoryService = BaseFactory.getFactory().getInstance(CategoryService.class);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServletException(e.getMessage());
        }
    }

    private boolean createPath(String path, Map<String, String> errorMsg) {
        File absUploadPathFile = new File(path);
        if (!absUploadPathFile.exists()) {
            boolean isSuccess = absUploadPathFile.mkdirs();
            if (!isSuccess) {
                System.out.println(path + " 目录创建失败！");
                errorMsg.put("all", "上传失败，请稍候重试！");
                return false;
            } else {
                return true;
            }
        }
        return true;
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1、使用第三方包解析文件表单
        Map<String, String> errorMsg = new HashMap<>();
        request.setAttribute("errorMsg", errorMsg);
        if (ServletFileUpload.isMultipartContent(request)) {
            // 是文件表单
            DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
            ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
            Map<String, String> formMap = new HashMap<>();
            try {
                List<FileItem> fileItems = servletFileUpload.parseRequest(request);

                for (FileItem fileItem : fileItems) {
                    if (fileItem.isFormField()) {
                        // 是普通表单字段
                        String key = fileItem.getFieldName();
                        String value = fileItem.getString("utf-8");
                        if (null != key && !"".equals(key)) {
                            formMap.put(key, value);
                        }
                    } else {
                        // 文件字段
                        InputStream inputStream = fileItem.getInputStream();

                        String absUploadPath = this.getServletContext().getRealPath(this.uploadPath);
                        if (!createPath(absUploadPath, errorMsg)) {
                            // 创建失败
                            errorMsg.put("all", "文件上传失败");
                            doGet(request, response);
                            return;
                        }

                        String absTempUploadPath = absUploadPath + "/temp";
                        if (!createPath(absTempUploadPath, errorMsg)) {
                            // 创建失败
                            errorMsg.put("all", "文件上传失败");
                            doGet(request, response);
                            return;
                        }

                        String tempFilePath = absTempUploadPath + "/" + UUID.randomUUID().toString();
                        File tempFile = new File(tempFilePath);
                        OutputStream outputStream = new FileOutputStream(tempFile);

                        MessageDigest md5 = MessageDigest.getInstance("md5");
                        byte[] buf = new byte[4096];
                        int result = inputStream.read(buf);
                        while (-1 != result) {
                            outputStream.write(buf, 0, result);
                            md5.update(buf, 0, result);
                            result = inputStream.read(buf);
                        }
                        outputStream.close();
                        fileItem.delete();
                        String fileMd5Code = new BigInteger(1, md5.digest()).toString(16);

                        // 生成8级目录
                        StringBuilder stringBuilder = new StringBuilder();
                        stringBuilder.append(absUploadPath);
                        for (int i = 0; i < 8; i++) {
                            stringBuilder.append("/");
                            stringBuilder.append(fileMd5Code.charAt(i));
                        }
                        String filePath = stringBuilder.toString();
                        if (!createPath(filePath, errorMsg)) {
                            // 创建失败
                            errorMsg.put("all", "文件上传失败");
                            doGet(request, response);
                            return;
                        }
                        File file = new File(filePath + "/" + fileMd5Code);
                        if (!file.exists()) {
                            boolean isSucces = tempFile.renameTo(file);
                            if (!tempFile.delete()) {
                                System.out.println(tempFile.getAbsoluteFile() + " 文件删除失败！");
                            }
                            if (!isSucces) {
                                // 移动失败
                                System.out.println(file.getAbsoluteFile() + " 文件移动失败！");
                                errorMsg.put("all", "文件上传失败");
                                doGet(request, response);
                                return;
                            }
                        }
                        // 上传成功
                        formMap.put(fileItem.getFieldName(), fileMd5Code);
                    }
                }


            } catch (FileUploadException e) {
                e.printStackTrace();
                errorMsg.put("all", "表单解析失败！");
                doGet(request, response);
                return;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
                errorMsg.put("all", "错误的加密算法！");
                doGet(request, response);
                return;
            }

            for (Map.Entry<String, String> entry : formMap.entrySet()) {
                System.out.println(entry.getKey() + "=" + entry.getValue());
            }

            // 表单验证
            String name = formMap.get("name");
            if (null == name || "".equals(name)) {
                errorMsg.put("name", "商品名称不能为空");
            }
            String cidString = formMap.get("cid");
            int cid = -1;
            if (null == cidString || "".equals(cidString)) {
                errorMsg.put("name", "请选择商品分类");
            } else {
                try{
                    cid = Integer.valueOf(cidString);
                }catch (NumberFormatException e) {
                    errorMsg.put("cid", "商品分类错误");
                }
            }

            String img = formMap.get("img");
            if (null == img || "".equals(img)) {
                errorMsg.put("img", "请上传商品图片");
            }

            String desc = formMap.get("desc");
            if (null == desc || "".equals(desc)) {
                errorMsg.put("desc", "商品描述不能为空");
            }


            if (0 == errorMsg.size()) {
                try {
                    // 判断分类是否存在
                    Category category = categoryService.getCategoryById(cid);
                    if (null == category) {
                        errorMsg.put("desc", "商品分类不存在！");
                    } else {
                        // 添加商品
                        Prod prod = new Prod();
                        prod.setCategory(category);
                        prod.setName(name);
                        prod.setDescription(desc);
                        prod.setImgUrl(img);
                        prod.setStatus(Prod.STATUS_NORMAL);
                        boolean isSucces = prodService.saveProd(prod);
                        if (!isSucces) {
                            errorMsg.put("all", "商品添加失败！");
                        }
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                    errorMsg.put("all", "商品添加失败，请稍候重试！");
                }
            }

            // 响应
            if (0 == errorMsg.size()) {
                // response.getWriter().write("ok");
                response.sendRedirect("ProdManageServlet");
            } else {
                doGet(request, response);
            }

        } else {
            // 不是文件表单
            errorMsg.put("all", "表单错误！");
            doGet(request, response);
        }

    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            List<Category> categoryList = categoryService.listCategoryAll();
            request.setAttribute("categoryList", categoryList);
            request.getRequestDispatcher("_prod_add.jsp").forward(request, response);
        } catch (SQLException e) {
            e.printStackTrace();
            response.setStatus(500);
        }
    }
}
